package com.lkd.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.github.wxpay.plus.WxPayParam;
import com.github.wxpay.plus.WxPayTemplate;
import com.lkd.common.VMSystem;
import com.lkd.config.TopicConfig;
import com.lkd.contract.OrderCheck;
import com.lkd.contract.VendoutContract;
import com.lkd.contract.VendoutData;
import com.lkd.contract.VendoutResultContract;
import com.lkd.dao.OrderDao;
import com.lkd.emq.MqttProducer;
import com.lkd.entity.OrderEntity;
import com.lkd.exception.LogicException;
import com.lkd.feign.UserServiceFeignClient;
import com.lkd.feign.VmServiceFeignClient;
import com.lkd.service.OrderService;
import com.lkd.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;


@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    private MqttProducer mqttProducer;
    @Autowired
    private WxPayTemplate wxPayTemplate;
    @Autowired
    private VmServiceFeignClient vmServiceFeignClient;
    @Autowired
    private UserServiceFeignClient userServiceFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> createOrder(PayVO payVO) {

        String innerCode = payVO.getInnerCode();
        Long skuId = payVO.getSkuId();

//        查询售货机数据
        VmVO vmVO = vmServiceFeignClient.getvmInfoByInnerCode(innerCode);
        if(vmVO == null){
            log.error("没有售货机数据");
            throw new LogicException("售后机不存在");
        }
//        查询当前商品是否还有库存
        ChannelVO channelVO = vmServiceFeignClient.hasCapacity(innerCode, skuId);
        if(channelVO == null){
            log.error("没有库存");
            throw new LogicException("商品没有库存");
        }
        SkuVO sku = channelVO.getSku();
        if(sku == null){
            log.error("没有库存");
            throw new LogicException("商品没有库存");
        }
//        创建订单
        OrderEntity orderEntity = new OrderEntity();
        BeanUtils.copyProperties(vmVO,orderEntity);
        orderEntity.setAddr(vmVO.getNodeAddr());
        orderEntity.setSkuId(skuId);
        BeanUtils.copyProperties(sku,orderEntity);

//        订单编号使用售货机编号 + 时间戳
        orderEntity.setOrderNo(innerCode + System.nanoTime());
        orderEntity.setStatus(VMSystem.ORDER_STATUS_CREATE);
        orderEntity.setAmount(sku.getPrice());
        PartnerVO partnerVO = userServiceFeignClient.getPartner(orderEntity.getOwnerId());
        Integer ratio = partnerVO.getRatio();//15 -》15%   （5 * 15 ）/100
//        合作商的分账金额
        int bill = new BigDecimal(orderEntity.getAmount()).multiply(new BigDecimal(ratio))
                .divide(new BigDecimal("100"), 0, RoundingMode.HALF_UP).intValue();
        orderEntity.setBill(bill);
        orderEntity.setPayType("2");
        orderEntity.setPayStatus(VMSystem.PAY_STATUS_NOPAY);


        orderEntity.setId(null);
        save(orderEntity);
//        发送延迟消息
        OrderCheck orderCheck = new OrderCheck();
        orderCheck.setInnerCode(innerCode);
        orderCheck.setOrderNo(orderEntity.getOrderNo());
        try {
//            延迟15秒
            mqttProducer.send("$delayed/15/"+TopicConfig.ORDER_CHECK_TOPIC,2,orderCheck);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (MqttException e) {
            e.printStackTrace();
            throw new LogicException("发送消息失败");
        }
//        调用微信支付
        WxPayParam wxPayParam = new WxPayParam();
        wxPayParam.setTotalFee(orderEntity.getAmount());
        wxPayParam.setOutTradeNo(orderEntity.getOrderNo());
        wxPayParam.setBody(sku.getSkuName());
        wxPayParam.setDuration(60L);
        Map<String, String> map = wxPayTemplate.requestPay(wxPayParam);
        return map;

    }

    @Override
    public void orderCheck(OrderCheck orderCheck) {

        String innerCode = orderCheck.getInnerCode();
        String orderNo = orderCheck.getOrderNo();
//        查询订单信息
        OrderEntity orderEntity = lambdaQuery().eq(OrderEntity::getOrderNo, orderNo).one();
        if(orderEntity == null){
            log.error("没有查询到订单数据");
        }
//        检查订单状态,订单状态==0，支付状态==0，没有支付
        if(orderEntity.getStatus() == VMSystem.ORDER_STATUS_CREATE &&
               orderEntity.getPayStatus() == VMSystem.PAY_STATUS_NOPAY){
//        如果没有支付，修改状态为关闭
//            update order set status=4 where order_no=? and status=0
            boolean b = lambdaUpdate()
                    .eq(OrderEntity::getOrderNo, orderNo)
                    .eq(OrderEntity::getStatus,VMSystem.ORDER_STATUS_CREATE)
                    .set(OrderEntity::getStatus, VMSystem.ORDER_STATUS_INVALID)
                    .set(OrderEntity::getCancelDesc, "超时未支付")
                    .update();
        }

    }

    @Override
    public void payNotify(Map<String, String> map) {

        String orderNo = map.get("order_sn");
        String openId = map.get("openId");
//        查询订单信息
        OrderEntity orderEntity = lambdaQuery().eq(OrderEntity::getOrderNo, orderNo).one();
        if(orderEntity == null){
            log.error("订单数据不存在");
            throw new LogicException("订单数据不存在");
        }
//        校验
        if(orderEntity.getPayStatus() != VMSystem.PAY_STATUS_NOPAY){
            log.error("订单状态异常，不是未支付");
            return;
        }
//        校验金额
        Integer price = Integer.valueOf(map.get("price"));
        if(orderEntity.getAmount().intValue() != price.intValue()){
            log.error("订单金额不匹配");
            throw new LogicException("订单金额不匹配");
        }

//        修改订单状态,保证幂等
        lambdaUpdate()
                .eq(OrderEntity::getOrderNo,orderNo)
                .eq(OrderEntity::getPayStatus,VMSystem.PAY_STATUS_NOPAY)
                .eq(OrderEntity::getStatus,VMSystem.ORDER_STATUS_CREATE)
                .set(OrderEntity::getOpenId,openId)
                .set(OrderEntity::getPayStatus,VMSystem.PAY_STATUS_PAYED)
                .set(OrderEntity::getStatus,VMSystem.ORDER_STATUS_PAYED)
                .update();
//        发送出货消息，给售货机服务
        VendoutContract vendoutContract = new VendoutContract();
        vendoutContract.setInnerCode(orderEntity.getInnerCode());
        VendoutData vendoutData = new VendoutData();
        vendoutData.setOrderNo(orderNo);
        vendoutData.setSkuId(orderEntity.getSkuId());
        vendoutContract.setVendoutData(vendoutData);
        try {
            mqttProducer.send(TopicConfig.VMS_VENDOUT_TOPIC,2,vendoutContract);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理出货结果通知
     * @param vendoutResultContract
     */
    @Override
    public void vendoutResult(VendoutResultContract vendoutResultContract) {
        boolean success = vendoutResultContract.isSuccess();
        String innerCode = vendoutResultContract.getInnerCode();
        VendoutData vendoutData = vendoutResultContract.getVendoutData();
        String orderNo = vendoutData.getOrderNo();
        if(success){
//          修改订单的状态。2-出货成功
            lambdaUpdate()
                    .eq(OrderEntity::getOrderNo,orderNo)
                    .set(OrderEntity::getStatus,VMSystem.ORDER_STATUS_VENDOUT_SUCCESS)
                    .update();
        }else{
//          修改订单的状态 3-出货失败
            lambdaUpdate()
                    .eq(OrderEntity::getOrderNo,orderNo)
                    .set(OrderEntity::getStatus,VMSystem.ORDER_STATUS_VENDOUT_FAIL)
                    .update();
//            TODO 退款 paystatus 2-退款中
            log.info("出货失败,发起退款 订单号:{}",orderNo);
        }

    }
}
